/*
Copyright [2023] [fuwen_soft]
*/
package vip.xiaonuo.modular.xypdf.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.spire.pdf.graphics.PdfMargins;
import com.spire.pdf.htmlconverter.qt.HtmlConverter;
import com.spire.pdf.htmlconverter.qt.Size;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.*;
import vip.xiaonuo.modular.xyethnic.entity.XyEthnic;
import vip.xiaonuo.modular.xyethnic.service.XyEthnicService;
import vip.xiaonuo.modular.xyethnic.vo.LineLevelsLogyVo;
import vip.xiaonuo.modular.xyethnic.vo.ListEthnicVo;
import vip.xiaonuo.modular.xyethniccate.entity.XyEthnicCate;
import vip.xiaonuo.modular.xyethniccate.service.XyEthnicCateService;
import vip.xiaonuo.modular.xylogy.entity.XyLogy;
import vip.xiaonuo.modular.xylogy.service.XyLogyService;
import vip.xiaonuo.modular.xylogytemplate.entity.XyLogyTemplate;
import vip.xiaonuo.modular.xylogytemplate.service.XyLogyTemplateService;
import vip.xiaonuo.modular.xypdf.entity.XyPdf;
import vip.xiaonuo.modular.xypdf.enums.XyPdfExceptionEnum;
import vip.xiaonuo.modular.xypdf.enums.XyPdfGenderConstant;
import vip.xiaonuo.modular.xypdf.form.PdfLogyGenderForm;
import vip.xiaonuo.modular.xypdf.mapper.XyPdfMapper;
import vip.xiaonuo.modular.xypdf.param.XyPdfParam;
import vip.xiaonuo.modular.xypdf.service.XyPdfService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.pdf.PdfSpireConfig;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static vip.xiaonuo.modular.xypdf.enums.XyPdfGenderConstant.*;

/**
 * 谱书service接口实现类
 *
 * @author yanwei
 * @date 2023-05-05 15:44:28
 */
@Service
@Slf4j
public class XyPdfServiceImpl extends ServiceImpl<XyPdfMapper, XyPdf> implements XyPdfService {

    @Autowired
    private XyLogyService xyLogyService;

    @Autowired
    private XyEthnicCateService xyEthnicCateService;

    @Autowired
    private XyLogyTemplateService xyLogyTemplateService;

    @Autowired
    private XyEthnicService xyEthnicService;

    @Autowired
    private PdfSpireConfig spireConfig;

    @Override
    public PageResult<XyPdf> page(XyPdfParam xyPdfParam) {
        QueryWrapper<XyPdf> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(xyPdfParam)) {

            // 根据模板编号 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getTemplateId())) {
                queryWrapper.lambda().eq(XyPdf::getTemplateId, xyPdfParam.getTemplateId());
            }
            // 根据家谱编号 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getLogyId())) {
                queryWrapper.lambda().eq(XyPdf::getLogyId, xyPdfParam.getLogyId());
            }
            // 根据创建人的用户编号 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getUserId())) {
                queryWrapper.lambda().eq(XyPdf::getUserId, xyPdfParam.getUserId());
            }
            // 根据编者 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getAuthor())) {
                queryWrapper.lambda().eq(XyPdf::getAuthor, xyPdfParam.getAuthor());
            }
            // 根据堂号 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getHallHost())) {
                queryWrapper.lambda().eq(XyPdf::getHallHost, xyPdfParam.getHallHost());
            }
            // 根据卷号 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getRollHost())) {
                queryWrapper.lambda().eq(XyPdf::getRollHost, xyPdfParam.getRollHost());
            }
            // 根据页眉谱名 查询
            if (ObjectUtil.isNotEmpty(xyPdfParam.getHeadName())) {
                queryWrapper.lambda().eq(XyPdf::getHeadName, xyPdfParam.getHeadName());
            }
        }
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<XyPdf> list(XyPdfParam xyPdfParam) {
        return this.list();
    }

    @Override
    public void add(XyPdfParam xyPdfParam) {
        XyPdf xyPdf = new XyPdf();
        BeanUtil.copyProperties(xyPdfParam, xyPdf);
        this.save(xyPdf);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<XyPdfParam> xyPdfParamList) {
        xyPdfParamList.forEach(xyPdfParam -> {
            this.removeById(xyPdfParam.getId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(XyPdfParam xyPdfParam) {
        XyPdf xyPdf = this.queryXyPdf(xyPdfParam);
        BeanUtil.copyProperties(xyPdfParam, xyPdf);
        this.updateById(xyPdf);
    }

    @Override
    public XyPdf detail(XyPdfParam xyPdfParam) {
        return this.queryXyPdf(xyPdfParam);
    }

    /**
     * 获取谱书
     *
     * @author yanwei
     * @date 2023-05-05 15:44:28
     */
    private XyPdf queryXyPdf(XyPdfParam xyPdfParam) {
        XyPdf xyPdf = this.getById(xyPdfParam.getId());
        if (ObjectUtil.isNull(xyPdf)) {
            throw new ServiceException(XyPdfExceptionEnum.NOT_EXIST);
        }
        return xyPdf;
    }

    @Override
    public void export(XyPdfParam xyPdfParam) {
        List<XyPdf> list = this.list(xyPdfParam);
        PoiUtil.exportExcelWithStream("SnowyXyPdf.xls", XyPdf.class, list);
    }


    /**
     * 生成规定的模板化
     * 不能增加事务!
     * @param pdfLogyGenderForm
     * @return
     */
    @Override
    public String genderPdfByLogyId(PdfLogyGenderForm pdfLogyGenderForm) {
        String pdfUrl = null;
        //String userId = LoginContextHolder.me().getSysLoginUser().getStrId();
        //xyLogyService.isAllAuthException(userId,pdfLogyGenderForm.getLogyId());
        // 此模板是否有固定路径呢？
        XyLogyTemplate logyTemplate = xyLogyTemplateService.getById(pdfLogyGenderForm.getTemplateId());
        Assert.isTrue(StrUtil.isNotBlank(logyTemplate.getTemLink()),"此模板暂未开通!");
        // 保存模板化
        XyPdf xyPdf = new XyPdf(null, pdfLogyGenderForm, pdfUrl);
        save(xyPdf);
        // 开始生成即可
        pdfUrl = doGenderPdfByLogyId(logyTemplate,pdfLogyGenderForm.getLogyId(),xyPdf.getId());
       // 进行模板化。
        if (StrUtil.isNotBlank(pdfUrl)){
            xyPdf.setPdfLink(pdfUrl);
            updateById(xyPdf);
        }


        return pdfUrl;
    }

    @Override
    public JSONObject pdfOpenLineChildList(String logyId) {
        XyLogy logy = xyLogyService.getById(logyId);
        com.alibaba.fastjson2.JSONObject dataJsonObj = new  com.alibaba.fastjson2.JSONObject();
        dataJsonObj.put("title",StrUtil.format("{}氏家谱",logy.getLogyName()));
        dataJsonObj.put("othoer",StrUtil.format("{}提供","富文网络"));
        dataJsonObj.put("time",StrUtil.format("{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
        // 这个集合，根据世 进行 排定，
        ArrayList<JSONObject> objects = Lists.newArrayList();
        List<LineLevelsLogyVo> lineLevelsLogyVos = xyEthnicService.lineChildList(logyId);
        for (LineLevelsLogyVo lineLevelsLogyVo : lineLevelsLogyVos) {
            // 开始组合数据
            com.alibaba.fastjson2.JSONObject dataJson = new  com.alibaba.fastjson2.JSONObject();
            dataJson.put("levelName",StrUtil.format("第{}世", NumFUtil.getCNNum(lineLevelsLogyVo.getLevel()) ));
            ArrayList<JSONObject> childList = Lists.newArrayList();
            List<ListEthnicVo> listEthnicVos = lineLevelsLogyVo.getListEthnicVos();

            for (ListEthnicVo listEthnicVo : listEthnicVos) {
                XyEthnic xyEthnic = xyEthnicService.getById(listEthnicVo.getId());

                com.alibaba.fastjson2.JSONObject dataJson2 = new  com.alibaba.fastjson2.JSONObject();
                // 头衔
                if (Integer.valueOf(1).equals(listEthnicVo.getLevels())){
                    dataJson2.put("sourceName","开基祖");
                    dataJsonObj.put("listDict",StrUtil.format("{}公派下",xyEthnic.getSurname()));
                }else{
                    // 需要找到对应的排行转义字符.
                    // 此人员的 排行转义
                    String joinId = xyEthnic.getJoinId();
                    XyEthnicCate xyEthnicCate = xyEthnicCateService.getById(joinId);
                    dataJson2.put("sourceName",StrUtil.blankToDefault(Objects.isNull(xyEthnicCate) ? "无记录" : xyEthnicCate.getJoinName(),"无记录"));
                }
                dataJson2.put("surname",xyEthnic.getSurname());
                commJson2(logyId, listEthnicVos, listEthnicVo, xyEthnic, dataJson2);
               //dataJson2.put("ethnicInfos",StrUtil.blankToDefault(xyEthnic.getEthnicInfo(),""));
                dataJson2.put("formDict",StrUtil.join(";",dataJson2.values()));
                childList.add(dataJson2);
            }

            dataJson.put("childList",childList);
            objects.add(dataJson);
        }
        dataJsonObj.put("topDeviceList",objects);
        return dataJsonObj;
    }

    /**
     *不带权限的那种 进行生成即可 核心方法。
     * @param logyTemplate
     * @param logyId
     * @return
     */
    private String doGenderPdfByLogyId(XyLogyTemplate logyTemplate, String logyId,String pdfId) {
        // 选择那套模板 进行实时渲染
        Assert.isTrue(XyPdfGenderConstant.PDF_TEM_IDS.contains(logyTemplate.getId()),"暂未找到对应模板类信息!");
        String pdfUrl = null;
        // 欧式模板
        pdfUrl = europeanStyleTem(logyTemplate,logyId,pdfId,pdfUrl);
        // 现代式模板
        pdfUrl = nowGlableStypeTem(logyTemplate,logyId,pdfId,pdfUrl);
        // 苏式模板
        // 通过 可执行文件生成啦
        pdfUrl = suStyleTem(logyTemplate,logyId,pdfId,pdfUrl);

        // 宝塔
        pdfUrl = treeStyleTem(logyTemplate, logyId,pdfId,pdfUrl);

        //碟记
        pdfUrl = dishStyleTem(logyTemplate,logyId,pdfId,pdfUrl);


       // Assert.isTrue(StrUtil.isNotBlank(pdfUrl),"生成失败,暂未找到对应模板类信息!");
         return pdfUrl;
        // 数据整合
        //ByteArrayOutputStream outputStream = PDTCommUtils.genderPdf(logyTemplate.getTemLink(), jsonObject());
    }

    private String suStyleTem(XyLogyTemplate logyTemplate, String logyId,String pdfId,String pdfUrl) {
        if (SOVIET_TEM.equals(logyTemplate.getId())){
            String suUrl = spireConfig.getSuUrl();
            // 苏方
            //return TencentCosUtil.uploadfile(new File(spireGetLocalFilePath(logyId, suUrl,pdfId)));
            return spireGetLocalFilePath(logyId, suUrl,pdfId);
        }
        return pdfUrl;
    }

    private String treeStyleTem(XyLogyTemplate logyTemplate, String logyId,String pdfId,String pdfUrl) {
        if (PAGODA_TEM.equals(logyTemplate.getId())){
            String treeUrl = spireConfig.getTreeUrl();
            // 苏方
            //return TencentCosUtil.uploadfile(new File(spireGetLocalFilePath(logyId, treeUrl,pdfId)));
            return spireGetLocalFilePath(logyId, treeUrl,pdfId);

        }
        return pdfUrl;
    }

    private String dishStyleTem(XyLogyTemplate logyTemplate, String logyId,String pdfId,String pdfUrl) {
        if (DISC_TEM.equals(logyTemplate.getId())){
            String dishUrl = spireConfig.getDishUrl();
            // 苏方
           // return TencentCosUtil.uploadfile(new File(spireGetLocalFilePath(logyId, dishUrl,pdfId)));
            return spireGetLocalFilePath(logyId, dishUrl,pdfId);
        }
        return pdfUrl;
    }


    @SneakyThrows
    private String spireGetLocalFilePath(String logyId, String suUrl,String pdfId) {
     //   String tempPaths = spireConfig.getTempPaths();
        String subFix = spireConfig.getSubFix();
       // String finalUrl = tempPaths.concat(IdUtil.objectId().concat(subFix));
       // DriveUtils.imgUntil(StrUtil.format(suUrl, logyId,false,IdUtil.objectId().concat(subFix),pdfId));
        //HtmlConverter.convert(StrUtil.format(suUrl, logyId), finalUrl, true, 9000000, new Size(1200f, 1000f), new PdfMargins(0));
        return StrUtil.format(suUrl, logyId,false,IdUtil.objectId().concat(subFix),pdfId);
    }

    private String nowGlableStypeTem(XyLogyTemplate logyTemplate, String logyId,String pdfId,String pdfUrl) {
        // 现代式
        if (MODERN_TEM.equals(logyTemplate.getId())){
            String nowUrl = spireConfig.getNowUrl();
            // 现代式
            //return TencentCosUtil.uploadfile(new File(spireGetLocalFilePath(logyId, suUrl,pdfId)));
            return spireGetLocalFilePath(logyId, nowUrl,pdfId);
//            XyLogy logy = xyLogyService.getById(logyId);
//            com.alibaba.fastjson2.JSONObject dataJsonObj = new  com.alibaba.fastjson2.JSONObject();
//            dataJsonObj.put("title",StrUtil.format("{}氏家谱",logy.getLogyName()));
//            dataJsonObj.put("othoer",StrUtil.format("{}提供","富文网络"));
//            dataJsonObj.put("time",StrUtil.format("{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
//            // 这个集合，根据世 进行 排定，
//            ArrayList<JSONObject> objects = Lists.newArrayList();
//            List<LineLevelsLogyVo> lineLevelsLogyVos = xyEthnicService.lineChildList(logyId);
//            for (LineLevelsLogyVo lineLevelsLogyVo : lineLevelsLogyVos) {
//                // 开始组合数据
//                com.alibaba.fastjson2.JSONObject dataJson = new  com.alibaba.fastjson2.JSONObject();
//                dataJson.put("levelName",StrUtil.format("第{}世",NumFUtil.getCNNum(lineLevelsLogyVo.getLevel())));
//                ArrayList<JSONObject> childList = Lists.newArrayList();
//                List<ListEthnicVo> listEthnicVos = lineLevelsLogyVo.getListEthnicVos();
//
//                for (ListEthnicVo listEthnicVo : listEthnicVos) {
//                    XyEthnic xyEthnic = xyEthnicService.getById(listEthnicVo.getId());
//
//                    com.alibaba.fastjson2.JSONObject dataJson2 = new  com.alibaba.fastjson2.JSONObject();
//                    // 头衔
//                    if (Integer.valueOf(1).equals(listEthnicVo.getLevels())){
//                        dataJson2.put("sourceName","开基祖");
//                    }else{
//                        // 需要找到对应的排行转义字符.
//                       // 此人员的 排行转义
//                        String joinId = xyEthnic.getJoinId();
//                        XyEthnicCate xyEthnicCate = xyEthnicCateService.getById(joinId);
//                        dataJson2.put("sourceName",StrUtil.blankToDefault(Objects.isNull(xyEthnicCate) ? "无记录" : xyEthnicCate.getJoinName(),"无记录"));
//                    }
//                    dataJson2.put("surname",xyEthnic.getSurname());
//                    commJson2(logyId, listEthnicVos, listEthnicVo, xyEthnic, dataJson2);
//                    dataJson2.put("formDict",StrUtil.join("；",dataJson2.values()));
//                    childList.add(dataJson2);
//                }
//
//                dataJson.put("childList",childList);
//                objects.add(dataJson);
//            }
//            dataJsonObj.put("topDeviceList",objects);
//            try {
//                return getPdfUrl(PDTCommUtils.genderPdf(logyTemplate.getTemLink(), dataJsonObj));
//            }catch (Exception e){
//                log.error(e.getMessage());
//            }
        }
        return pdfUrl;
    }

    private void commJson2(String logyId, List<ListEthnicVo> listEthnicVos, ListEthnicVo listEthnicVo, XyEthnic xyEthnic, JSONObject dataJson2) {
        dataJson2.put("name", listEthnicVo.getName());
        dataJson2.put("existUser",Long.valueOf(2).equals(xyEthnic.getExistUser()) ? "不在世" : "在世");
        dataJson2.put("broThDate",StrUtil.format("生庚{}","请选择".equals(xyEthnic.getNewDate()) ? "未详": StrUtil.emptyToDefault(xyEthnic.getNewDate(),"未详")));
        dataJson2.put("xifus",StrUtil.join(",", listEthnicVo.getBinEthnicVos().stream().map(item -> StrUtil.format("娶{}氏,姓名{}\r", item.getSurname(),item.getName())).distinct().toArray()));

        List<XyEthnic> xyEthnicList = xyEthnicService.list(Wrappers.<XyEthnic>lambdaQuery().eq(XyEthnic::getLogyId, logyId).eq(XyEthnic::getParentId, xyEthnic.getId()).isNull(XyEthnic::getIsJoin));
        Map<Long, List<XyEthnic>> collect = xyEthnicList.stream().collect(Collectors.groupingBy(XyEthnic::getGenderSex));
        if (collect.get(1L) != null)
            dataJson2.put("manFormDict",StrUtil.format("生:{}子,{}",collect.get(1L).size(),StrUtil.join(",",collect.get(1L).stream().map(XyEthnic::getName).distinct().toArray())));
        if (collect.get(2L) != null)
            dataJson2.put("womanFormDict",StrUtil.format("生:{}女,{}",collect.get(2L).size(),StrUtil.join(",", collect.get(2L).stream().map(XyEthnic::getName).distinct().toArray())));

    }

    private String europeanStyleTem(XyLogyTemplate logyTemplate, String logyId,String pdfId,String pdfUrl) {
        if (EUR_TEM.equals(logyTemplate.getId())){
           // XyLogy logy = xyLogyService.getById(logyId);
            String ouUrl = spireConfig.getOuUrl();
            // 欧式
            //return TencentCosUtil.uploadfile(new File(spireGetLocalFilePath(logyId, suUrl,pdfId)));
            return spireGetLocalFilePath(logyId, ouUrl,pdfId);
            // 开始生成
            // 预备数据
//            com.alibaba.fastjson2.JSONObject dataJsonObj = new  com.alibaba.fastjson2.JSONObject();
//            // 家谱名称
//            dataJsonObj.put("title",StrUtil.format("{}氏家谱",logy.getLogyName()));
//            dataJsonObj.put("othoer",StrUtil.format("{}提供","富文网络"));
//            dataJsonObj.put("time",StrUtil.format("{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
//            // 这个集合，根据世 进行 排定，
//            List<LineLevelsLogyVo> lineLevelsLogyVos = xyEthnicService.lineChildList(logyId);
//            // 行转列表
//            ArrayList<JSONObject> objects = Lists.newArrayList();
//            for (LineLevelsLogyVo lineLevelsLogyVo : lineLevelsLogyVos) {
//                List<ListEthnicVo> listEthnicVos = lineLevelsLogyVo.getListEthnicVos();
//                com.alibaba.fastjson2.JSONObject dataJson = new  com.alibaba.fastjson2.JSONObject();
//                dataJson.put("levelName",StrUtil.format("第{}世",NumFUtil.getCNNum(lineLevelsLogyVo.getLevel())));
//                // 拼接下方的具体数据
//                ArrayList<JSONObject> childList = Lists.newArrayList();
//                for (ListEthnicVo listEthnicVo : listEthnicVos) {
//                    com.alibaba.fastjson2.JSONObject dataJson2 = new  com.alibaba.fastjson2.JSONObject();
//                    XyEthnic xyEthnic = xyEthnicService.getById(listEthnicVo.getId());
//                    commJson2(logyId, listEthnicVos, listEthnicVo, xyEthnic, dataJson2);
//                    childList.add(dataJson2);
//                }
//                dataJson.put("childList",childList);
//                objects.add(dataJson);
//            }
//
//            dataJsonObj.put("topDeviceList",objects);
//            try {
//                return getPdfUrl(PDTCommUtils.genderPdf(logyTemplate.getTemLink(), dataJsonObj));
//            }catch (Exception e){
//                log.error(e.getMessage());
//            }

        }
        return pdfUrl;
    }

    private  String getPdfUrl(ByteArrayOutputStream outputStream) throws IOException {
        String tempPaths = spireConfig.getTempPaths();
        String subFix = spireConfig.getSubFix();
        //  String outputFileClass = ResourceUtil.getResourceAbsolutePathByClassPath("./");

        // 生成pdf路径
        // generate pdf path
        String outputFile = new File(tempPaths)
                .getParentFile().getParent()
                +System.currentTimeMillis() + subFix;
        IOUtils.write(outputStream.toByteArray(), Files.newOutputStream(Paths.get(outputFile)));
        outputStream.flush();
        outputStream.close();
        return TencentCosUtil.uploadfile(new File(outputFile));
    }

}
